// Copyright 2022 jeff.li. and/or its affiliates.

#include <cxxabi.h>

#include <tbir/runtime/demangle.h>

namespace tbir::runtime {

    String Demangle(const char *mangled) {
        String msg(mangled);
        size_t symbol_start = String::npos;
        size_t symbol_end = String::npos;
        if (((symbol_start = msg.find("_Z")) != String::npos) &&
            (symbol_end = msg.find_first_of(" +", symbol_start))) {
            String left_of_symbol(msg, 0, symbol_start);
            String symbol(msg, symbol_start, symbol_end - symbol_start);
            String right_of_symbol(msg, symbol_end);

            int status = 0;
            size_t length = symbol.size();
            std::unique_ptr<char, void (*)(void *__ptr)> demangled_symbol = {
                    abi::__cxa_demangle(symbol.c_str(), nullptr, &length, &status), &std::free};
            if (demangled_symbol && status == 0 && length > 0) {
                return left_of_symbol + String(demangled_symbol.get()) + right_of_symbol;
            }
        }
        return String(mangled);
    }

    String DemangleType(const char *mangled) {
        String symbol(mangled);
        int status = 0;
        size_t length = symbol.size();
        std::unique_ptr<char, void (*)(void *__ptr)> demangled_symbol = {
                abi::__cxa_demangle(symbol.c_str(), nullptr, &length, &status), &std::free};
        if (demangled_symbol && status == 0 && length > 0) {
            return String(demangled_symbol.get());
        }
        return String(mangled);
    }

}  // namespace tbir::runtime
